package com.yanqu.road.server.manger.activity.assistantcostumemall;

import com.yanqu.road.dao.impl.activity.assistantcostumemall.AssistantCostumeMallDaoImpl;
import com.yanqu.road.entity.activity.ActivityConfig;
import com.yanqu.road.entity.activity.ActivityInfo;
import com.yanqu.road.entity.activity.assistantcostumemall.AssistantCostumeMallConfig;
import com.yanqu.road.entity.activity.assistantcostumemall.AssistantMallRandomGoods;
import com.yanqu.road.entity.activity.mall.MallActivityInfo;
import com.yanqu.road.entity.config.goods.MallInfo;
import com.yanqu.road.entity.enums.eActivityType;
import com.yanqu.road.entity.enums.eShopType;
import com.yanqu.road.entity.goods.MallRandomGoods;
import com.yanqu.road.entity.servercenter.ServerInfo;
import com.yanqu.road.logic.bussiness.servercenter.ActivityBussiness;
import com.yanqu.road.server.GameServer;
import com.yanqu.road.server.TempMgr;
import com.yanqu.road.server.manger.ServerListMgr;
import com.yanqu.road.server.manger.activity.MallActivityMgr;
import com.yanqu.road.server.manger.activity.NormalActivityMgr;
import com.yanqu.road.server.manger.config.MallMgr;
import com.yanqu.road.server.manger.config.MallRechargeConfigMgr;
import com.yanqu.road.utils.LocalDateTimeHelper;
import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.string.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author ：zfr
 * @date ：2022/3/23 11:00
 */
public class AssistantCostumeMallActivityMgr extends TempMgr {
    private static AssistantCostumeMallConfig config;
    private static AssistantMallRandomGoods randomGoods;

    //v4.9
    private static Map<String, ActivityConfig> configMap;

    private static Random random = new Random();

    public static MallInfo getMallInfoByMallId(int mallId) {
        if (randomGoods.getMallIdList().contains(mallId)) {
            Map<Integer, MallInfo> goods = getMallMapInTime();
            if (goods != null) {
                return goods.get(mallId);
            }
        }
        return null;
    }

    @Override
    public boolean init() throws Exception {
        return reload();
    }

    @Override
    public boolean reloadConfig() throws Exception {
        return true;
    }

    @Override
    public boolean reloadData() throws Exception {
        return true;
    }

    private static Map<Integer, MallInfo> getMallMapInTime() {
        int openActivityId = getOpenActivityId();
        if (openActivityId == 0) {
            return null;
        }
        MallActivityInfo inTimeActivity = MallActivityMgr.getInTimeActivity(openActivityId);
        if (inTimeActivity == null) {
            return null;
        }
        return inTimeActivity.getMallInfoMap();
    }

    private static void generateRandomMallInfo(int activityId) {
        int num;
        ServerInfo serverInfo = ServerListMgr.getServerInfo(GameServer.getInstance().getServerId());
        if(serverInfo == null){
            return;
        }
        int days = DateHelper.calc2DateTDOADays(new Date(serverInfo.getOpenTime() * 1000), new Date());
        if(config.getAssistantRefreshCount().length() == 1){
            num = Integer.valueOf(config.getAssistantRefreshCount());
        }else {
            num = getShowNumByOpenDays(config.getAssistantRefreshCount(), days);
        }
        if (randomGoods == null || randomGoods.getActivityId() != activityId) {
            randomGoods = new AssistantMallRandomGoods();
            randomGoods.setActivityId(activityId);
            randomGoods.setShopType(eShopType.AssistantSkinMall.getValue());
            setNewMallIdInToMallRandomGoods(randomGoods, num, days);
            randomGoods.setInsertOption();
        } else {
            setNewMallIdInToMallRandomGoods(randomGoods, num, days);
        }
    }

    public static void setNewMallIdInToMallRandomGoods(AssistantMallRandomGoods mallRandomGoods, int num, int openDays) {
        if (mallRandomGoods == null) {
            return;
        }
        //初始皮肤兑换商店
        Map<Integer, MallInfo> goods = getMallMapInTime();
        if (goods == null) {
            return;
        }
        Map<Integer, MallInfo> goodsMap = new HashMap<>();
        for (Map.Entry<Integer, MallInfo> infoEntry : goods.entrySet()) {
            if(infoEntry.getValue().getShopType() == eShopType.AssistantSkinMall.getValue()){
                goodsMap.put(infoEntry.getKey(), infoEntry.getValue());
                getLogger().info("mallRandomGoods assistant {}：{}", infoEntry.getValue().getMallId(), infoEntry.getValue().getShopType());
            }
        }
        goods = goodsMap;
        int model = config.getAssistantRefreshMode();
        if (model == 1) {
            //按套装
            Map<Integer, List<MallInfo>> suitMap = new HashMap<>();
            for (MallInfo mallInfo : goods.values()) {
                int suitType = (int)MallRechargeConfigMgr.getParamValue(mallInfo);
//                int suitType = Integer.parseInt(mallInfo.getParam());
                List<Integer> exParamList = StringUtils.stringToIntegerList(mallInfo.getExtendParam(), "\\|");
                if(exParamList.size() == 2){
                    //排除未开放的
                    if(openDays < exParamList.get(1)){
                        continue;
                    }
                }
                if (!suitMap.containsKey(suitType)) {
                    suitMap.put(suitType, new ArrayList<>());
                }
                suitMap.get(suitType).add(mallInfo);
            }
            Map<Integer, Integer> suitWeightMap = new HashMap<>();
            for (Map.Entry<Integer, List<MallInfo>> listEntry : suitMap.entrySet()) {
                int totalWeight = listEntry.getValue().stream().mapToInt(mallInfo -> StringUtils.stringToIntegerList(mallInfo.getExtendParam(), "\\|").get(0)).sum();
                int averageWeight = totalWeight / listEntry.getValue().size() + totalWeight % listEntry.getValue().size() > 0 ? 1 : 0;
                suitWeightMap.put(listEntry.getKey(), averageWeight);
            }
            Map<Integer, List<MallInfo>> randomSuitMap = new HashMap<>();
            while (suitWeightMap.size() > 0 && randomSuitMap.size() < num) {
                int suitType = RandomHelper.getRandomKeyByWeight(suitWeightMap);
                randomSuitMap.put(suitType, suitMap.get(suitType));
                suitWeightMap.remove(suitType);
            }
            List<Integer> mallIdList = new ArrayList<>();
            for (List<MallInfo> mallInfos : randomSuitMap.values()) {
                mallIdList.addAll(mallInfos.stream().map(MallInfo::getMallId).collect(Collectors.toList()));
            }
            mallRandomGoods.setMallIdList(mallIdList);
            mallRandomGoods.setLastUpdateTime(LocalDateTimeHelper.getZeroTimeTimeStamp());
        } else {
            Map<Integer, MallInfo> poolList = new HashMap<>();
            Map<Integer, Integer> mallWeightMap = new HashMap<>();
            for (Map.Entry<Integer, MallInfo> mallInfoEntry : goods.entrySet()) {
                List<Integer> paramList = StringUtils.stringToIntegerList(mallInfoEntry.getValue().getExtendParam(), "\\|");
                if(paramList.size() == 2){
                    //排除未开放的
                    if(openDays < paramList.get(1)){
                        continue;
                    }
                }
                poolList.put(mallInfoEntry.getKey(), mallInfoEntry.getValue());
                mallWeightMap.put(mallInfoEntry.getKey(), paramList.get(0));
            }
            Map<Integer, MallInfo> randomMallMap = new HashMap<>();
            while (mallWeightMap.size() > 0 && randomMallMap.size() < num) {
                int mallId = RandomHelper.getRandomKeyByWeight(mallWeightMap);
                randomMallMap.put(mallId, poolList.get(mallId));
                mallWeightMap.remove(mallId);
            }
            List<Integer> mallIdList = randomMallMap.values().stream().map(MallInfo::getMallId).collect(Collectors.toList());
            mallRandomGoods.setMallIdList(mallIdList);
            mallRandomGoods.setLastUpdateTime(LocalDateTimeHelper.getZeroTimeTimeStamp());
        }
    }

    public static void reloadActivityData() {
        getLogger().info("reload assistant costume mall activity start");
        List<ActivityInfo> openActivityInfoList = NormalActivityMgr.getOpenActivityInfoList(eActivityType.AssistantCostumeExchangeMallActivity.getValue());
        if (openActivityInfoList.size() <= 0) {
            getLogger().info("reload assistant costume mall activity finish, no activity in show time.");
            config = null;
            configMap = null;
            return;
        }
        int activityId = openActivityInfoList.get(0).getActivityId();
        List<Integer> activityIdList = new ArrayList<>();
        activityIdList.add(activityId);
        Map<String, ActivityConfig> activityConfigMap = ActivityBussiness.getActivityConfigMap(activityIdList).get(activityId);
        config = new AssistantCostumeMallConfig(activityConfigMap);

        if (randomGoods == null || randomGoods.getActivityId() != activityId) {
            randomGoods = new AssistantCostumeMallDaoImpl().getGoodsInfo(activityId);
        }

        configMap = activityConfigMap;
        //v4.9 门客、美女随机兑换商店
        if(randomGoods == null || randomGoods.getActivityId() != activityId) {
            MallMgr.generateRandomMallInfo(eShopType.BeautySkinMall.getValue(), 0, true);
            MallMgr.generateRandomMallInfo(eShopType.PatronsSkinMall.getValue(), 0, true);
        }
        checkMallRandomGoodsRefresh();

        getLogger().info("reload assistant costume mall activity finish, activityId {}", activityId);
    }

    public static int getOpenActivityId() {
        List<ActivityInfo> openActivityInfoList = NormalActivityMgr.getOpenActivityInfoList(eActivityType.AssistantCostumeExchangeMallActivity.getValue());
        if (openActivityInfoList.size() > 0) {
            return openActivityInfoList.get(0).getActivityId();
        }
        return 0;
    }

    public static synchronized void checkMallRandomGoodsRefresh() {
        int openActivityId = getOpenActivityId();
        if (openActivityId > 0) {
            if (randomGoods == null) {
                generateRandomMallInfo(openActivityId);
                return;
            }
            if (randomGoods.getActivityId() == openActivityId) {
                if (DateHelper.calc2DateTDOADays(new Date(randomGoods.getLastUpdateTime()), new Date()) > config.getAssistantRefreshTime()) {
                    generateRandomMallInfo(openActivityId);
                }
            }
        }
    }

    public static AssistantMallRandomGoods getMallRandomGoods() {
        checkMallRandomGoodsRefresh();
        return randomGoods;
    }

    @Override
    public boolean stop() {
        return false;
    }

    @Override
    public boolean save() {
        if (randomGoods != null) {
            if (randomGoods.isInsertOption()) {
                new AssistantCostumeMallDaoImpl().add(randomGoods);
            } else if (randomGoods.isUpdateOption()) {
                new AssistantCostumeMallDaoImpl().update(randomGoods);
            }
        }
        return true;
    }

    /**
     * 刷新原绫罗阁皮肤兑换商品
     */
    public static boolean refreshRandomGoods(MallRandomGoods mallRandomGoods, int shopType, boolean force) {
        if(config == null || configMap == null){
            getLogger().info("refreshRandomGoods config is null");
            return false;
        }

        if(!force){
            //时间不到，不刷新
            long zeroTime = LocalDateTimeHelper.getZeroTimeTimeStamp();
            if(mallRandomGoods.getLastUpdateTime() >= zeroTime){
                return true;
            }
        }

        Map<Integer, MallInfo> mallMap = getMallMapInTime();
        if (mallMap == null) {
            getLogger().info("refreshRandomGoods mallMap is null");
            return false;
        }

        //获取展示数量
        ActivityConfig activityConfig = configMap.get("REFRESH_COUNT_" + shopType);
        if(activityConfig == null){
            getLogger().info("refreshRandomGoods activityConfig is null");
            return false;
        }
        String REFRESH_COUNT = activityConfig.getValue();

        //开服天数
        int days = ServerListMgr.getServerOpenDay(GameServer.getInstance().getServerId());
        getLogger().info("refreshRandomGoods days is {}", days);

        List<MallInfo> mallInfoList = getMallInfosLimitByServerOpenDays(shopType, mallMap, days);

        int num = getShowNumByOpenDays(REFRESH_COUNT, days);
        if(num == 0){
            getLogger().info("refreshRandomGoods num is null");
            return false;
        }

        List<Integer> mallIdList = new ArrayList<>();
        while (mallInfoList.size() > 0 && num > 0){
            List<Integer> weightList = new ArrayList<>();
            for (MallInfo mallInfo : mallInfoList) {
                weightList.add((int)MallRechargeConfigMgr.getParamValue(mallInfo));
//                weightList.add(Integer.parseInt(mallInfo.getParam()));
            }
            int idx = RandomHelper.getRandomIndexByWeight(weightList, random);
            MallInfo mallInfo = mallInfoList.remove(idx);
            mallIdList.add(mallInfo.getMallId());
            num--;
        }

        mallRandomGoods.setMallIdList(mallIdList);
        //暂时每日重置
        mallRandomGoods.setLastUpdateTime(LocalDateTimeHelper.getZeroTimeTimeStamp());
        getLogger().info("refreshRandomGoods type {} ids: {}, force : {}", shopType, StringUtils.listToString(mallIdList, ","), force);
        return true;
    }

    public static List<MallInfo> getMallInfosLimitByServerOpenDays(int shopType, Map<Integer, MallInfo> mallMap, int days) {
        List<MallInfo> mallInfoList = new ArrayList<>();
        for (Map.Entry<Integer, MallInfo> infoEntry : mallMap.entrySet()) {
            List<Integer> exParamList = StringUtils.stringToIntegerList(infoEntry.getValue().getExtendParam(), "\\|");
            if(infoEntry.getValue().getShopType() == shopType && days > exParamList.get(0)){
                mallInfoList.add(infoEntry.getValue());
            }
        }
        return mallInfoList;
    }

    public static List<MallInfo> getMallInfosLimitByServerOpenDays(int shopType){
        List<MallInfo> result = new ArrayList<>();
        Map<Integer, MallInfo> mallMap = getMallMapInTime();
        if (mallMap == null) {
            return result;
        }
        if(config == null || configMap == null){
            return result;
        }
        ActivityConfig activityConfig = configMap.get("REFRESH_COUNT_" + shopType);
        if(activityConfig == null){
            return result;
        }
        //开服天数
        int days = ServerListMgr.getServerOpenDay(GameServer.getInstance().getServerId());
        result = getMallInfosLimitByServerOpenDays(shopType, mallMap, days);
        return result;
    }

    private static int getShowNumByOpenDays(String refresh_count, int days) {
        int num = 0;
        List<String> strList = StringUtils.stringToStringList(refresh_count, "\\|");
        for (String s : strList) {
            List<Integer> list = StringUtils.stringToIntegerList(s, ";");
            if(list.size() == 2){
                if(days >= list.get(0)){
                    num = list.get(1);
                }
            }
        }
        return num;
    }
}
